﻿using SearchAlgorithms.Interfaces;
using System;
using System.Linq;
using System.Numerics;
using System.Runtime.CompilerServices;
using System.Security.Cryptography;

namespace SearchAlgorithms.Algorithms.Compare
{
    public class CompareWithMethod : ICompareAlgorithm
    {
        /// <summary>
        /// 比较两个字节数组是否完全相同。
        /// </summary>
        /// <param name="frameA">要比较的第一个字节数组。</param>
        /// <param name="frameB">要比较的第二个字节数组。</param>
        /// <returns>如果两个数组完全相同，返回 true；否则返回 false。</returns>
        public bool Comparison(byte[] frameA, byte[] frameB)
        {
            if (frameA.Length != frameB.Length)
            {
                return false;
            }

            for (int i = 0; i < frameA.Length; i++)
            {
                if (frameA[i] != frameB[i])
                {
                    return false;
                }
            }
            return true;
        }

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public bool Comparison(Span<byte> frameA, Span<byte> frameB)
        {
            if (frameA.Length != frameB.Length)
            {
                return false;
            }

            for (int i = 0; i < frameA.Length; i++)
            {
                if (frameA[i] != frameB[i])
                {
                    return false;
                }
            }
            return true;
        }

        public bool Comparison2(Span<byte> spanA, Span<byte> spanB)
        {
            if (spanA.Length != spanB.Length)
                return false;  // 如果两个 Span 的长度不同，直接返回 false

            int vectorSize = Vector<byte>.Count;  // 获取 SIMD 向量的元素数量（即一次性可以处理多少字节）
            int i = 0;  // 定义循环变量

            // 批量处理，直到处理完所有可以用 SIMD 向量处理的部分
            for (; i <= spanA.Length - vectorSize; i += vectorSize)
            {
                // 取出从索引 i 开始的 vectorSize 长度的子范围（slice），创建向量
                var vecA = new Vector<byte>(spanA.Slice(i, vectorSize));
                var vecB = new Vector<byte>(spanB.Slice(i, vectorSize));

                // 比较两个向量的所有字节是否相同
                if (!Vector.EqualsAll(vecA, vecB))
                    return false;  // 如果发现有不相等的字节，返回 false
            }

            // 处理剩下的不能整除向量大小的部分
            for (; i < spanA.Length; i++)
            {
                if (spanA[i] != spanB[i])  // 逐字节比较
                    return false;  // 如果有不相等的字节，返回 false
            }

            return true;  // 如果没有找到不相等的字节，返回 true
        }

        /// <summary>
        /// LINQ语句比较两个字节数组是否按顺序完全相同。
        /// </summary>
        /// <param name="src">要比较的源字节数组。</param>
        /// <param name="dst">要比较的目标字节数组。</param>
        /// <returns>如果两个数组长度相同且每个对应位置上的字节都相同，返回 true；否则返回 false。</returns>
        public bool CompareWithSequence(byte[] src, byte[] dst)
        {
            return src.SequenceEqual(dst);
        }

        public bool CompareWithSequence(Span<byte> src, Span<byte> dst)
        {
            return src.SequenceEqual(dst);
        }

        public bool CompareWithHash(byte[] src, byte[] dst, HashAlgorithm hash)
        {
            byte[] hashSrc = hash.ComputeHash(src);
            byte[] hashDst = hash.ComputeHash(dst);
            
            return hashSrc.SequenceEqual(hashDst);
        }

        public bool CompareWithHashAsSpan (byte[] src, byte[] dst, HashAlgorithm hash)
        {
            // 计算源和目标的哈希值
            Span<byte> HashSrc = hash.ComputeHash(src);
            Span<byte> HashDst = hash.ComputeHash(dst);

            // 比较两个哈希值
            return HashSrc.SequenceEqual(HashDst);
        }
    }
}
